package com.sisgesbyte.services.proyeccion;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Inject;
import com.sisgesbyte.common.ConstModAdministracion;
import com.sisgesbyte.common.ConstProyeccion;
import com.sisgesbyte.common.ConstantesInternasSistema;
import com.sisgesbyte.common.Validaciones;
import com.sisgesbyte.dao.beanDao.FiltrosBean;
import com.sisgesbyte.dao.beanDao.FiltrosSQLBean;
import com.sisgesbyte.dao.proyeccion.MantBandaProyeccionDao;
import com.sisgesbyte.dao.proyeccion.MantProyeccionProductoGeneralDao;
import com.sisgesbyte.dao.proyeccion.MantProyeccionProductoPeriodoDao;
import com.sisgesbyte.dao.ventas.ConsultaVentasDao;
import com.sisgesbyte.data.entity.proyeccion.BandaProyeccionEntity;
import com.sisgesbyte.data.entity.proyeccion.ProyeccionProductoGeneralEntity;
import com.sisgesbyte.data.entity.proyeccion.ProyeccionProductoPeriodoEntity;
import com.sisgesbyte.data.entity.ventas.VentasEntity;
import com.sisgesbyte.services.proyeccion.bean.AvancePeriodoProductoBean;
import com.sisgesbyte.services.proyeccion.bean.AvanceProductosResponse;
import com.sisgesbyte.services.proyeccion.bean.AvanceTotalProductoBean;
import com.sisgesbyte.services.proyeccion.bean.ProductoProyeccionBean;

@Stateless
public class ProyeccionProductoPorPeriodoServiceImpl implements ProyeccionProductoPorPeriodoService {

	@EJB
	private MantProyeccionProductoGeneralDao mantProyeccionProductoGeneralDao;
	@EJB
	private MantProyeccionProductoPeriodoDao mantProyeccionProductoPeriodoDao;
	@EJB
	private MantBandaProyeccionDao mantBandaProyeccionDao;
	@EJB
	private ConsultaVentasDao consultaVentasDao;
	@Inject
	private Validaciones validaciones;
	
	@Override
	public AvanceProductosResponse listaAvanceProductosPorPeriodo(String codTransaccion,FiltrosSQLBean filtros,int idPeriodo) {
		String mensajeTransaccionMetodo = "[listaAvanceProductosPorPeriodo idTx=" + codTransaccion + "] - ";
		AvanceProductosResponse response = new AvanceProductosResponse();
		try{
			 response.setIdTransaccion(codTransaccion);
			 
			 List<ProyeccionProductoGeneralEntity> productoProyeccionGeneral=null;
			 try{
				 //1.- Capturamos la lista de proyeccion general por producto
				productoProyeccionGeneral = mantProyeccionProductoGeneralDao.listaProyeccionProductoGeneral(filtros);
			 }catch(Exception e){
				System.out.println(mensajeTransaccionMetodo+"Ocurrio un Error al Obtener la lista de proyeccion de productos general- " + e);
				response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
				response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
				return response;
			 }
			 if(productoProyeccionGeneral.size() > 0){
				 List<ProductoProyeccionBean> listaProyeccionProductos = new ArrayList<ProductoProyeccionBean>();
				 for(ProyeccionProductoGeneralEntity row : productoProyeccionGeneral){
					 ProductoProyeccionBean productoProyeccion = new ProductoProyeccionBean();
					 productoProyeccion.setIdCategoriaProducto(row.getCategoria_producto_id());
					 productoProyeccion.setCategoriaProducto(validaciones.validarCamposString(row.getCategoria()));
					 productoProyeccion.setIdProducto(row.getProducto_id());
					 productoProyeccion.setCodProducto(validaciones.validarCamposString(row.getCod_prod()));
					 productoProyeccion.setProducto(validaciones.validarCamposString(row.getProducto()));
					 productoProyeccion.setPrecioPromedio(row.getPrecio_promedio());
					 
					 AvanceTotalProductoBean avanceGeneral = new AvanceTotalProductoBean();
					 avanceGeneral.setUnidadesTotalProyeccion(row.getCantidad_proyectada());
					 try{
						 avanceGeneral.setTotalMontoProyeccion(row.getPrecio_promedio().multiply(row.getCantidad_proyectada()));
					 }catch(Exception e){
						 avanceGeneral.setTotalMontoProyeccion(BigDecimal.ZERO);
					 }
					
					 List<VentasEntity> ventasPorProductoGeneral = null;
					 try{
						 FiltrosSQLBean cadenaFiltros = new FiltrosSQLBean();
						 List<FiltrosBean> listaFiltros = new ArrayList<FiltrosBean>();
						 FiltrosBean filtroCampos = new FiltrosBean();
						 List<String> campos = new ArrayList<String>();
						 campos.add("bonificacion");
						 campos.add("producto_id");
						 filtroCampos.setCampos(campos);
						 filtroCampos.setOperador("=");
						 listaFiltros.add(filtroCampos);
						 List<Object> valores = new ArrayList<Object>();
						 valores.add(false);
						 valores.add(row.getProducto_id());
						 cadenaFiltros.setListaFiltros(listaFiltros);
						 cadenaFiltros.setListaValores(valores);
						 //2.- Capturamos la venta y unidades total de cada producto
						 ventasPorProductoGeneral = consultaVentasDao.listaVentasDetalle(cadenaFiltros);
					 }catch(Exception e){
						System.out.println(mensajeTransaccionMetodo+"Ocurrio un Error al Obtener la lista de proyeccion de productos general- " + e);
						response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
						response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
						return response;
					 }
					 
					 BigDecimal montoTotal = BigDecimal.ZERO;
					 BigDecimal unidadesTotal = BigDecimal.ZERO;
					 if(ventasPorProductoGeneral.size() > 0){
						 for(VentasEntity ventas :  ventasPorProductoGeneral){
							 montoTotal = montoTotal.add(ventas.getTotal());
							 unidadesTotal = unidadesTotal.add(ventas.getCantidad());
						 }
					 }
					 avanceGeneral.setTotalMontoAvance(montoTotal);
					 avanceGeneral.setUnidadesTotalAvance(unidadesTotal);
					 
					 BigDecimal porcentajeMonto = BigDecimal.ZERO;
					 try{
						 porcentajeMonto = (montoTotal).divide(row.getPrecio_promedio().multiply(row.getCantidad_proyectada()),4, RoundingMode.CEILING);
					 }catch(Exception e){
						 System.out.println("Error al dividir "+ e);
					 }
					 BigDecimal porcentajeUnidades = BigDecimal.ZERO;
					 try{
						 porcentajeUnidades = unidadesTotal.divide(row.getCantidad_proyectada(),4, RoundingMode.CEILING);
					 }catch(Exception e){
						 System.out.println("Error al dividir "+ e);
					 }
					 avanceGeneral.setPorcentageMontoAvance(porcentajeMonto.multiply(new BigDecimal(100)));
					 avanceGeneral.setPorcentageUnidadesAvance(porcentajeUnidades.multiply(new BigDecimal(100)));
					
					try{
						//3.- Capturamos la banda para proyeccion general de productos
						 avanceGeneral.setBandaProyeccion(listaBandas(row.getCodigo_banda()));
					}catch(Exception e){
						avanceGeneral.setBandaProyeccion(null);
					}
					
					 try{
						 avanceGeneral.setColorBanda(colorBanda(listaBandas(row.getCodigo_banda()), porcentajeUnidades));
					 }catch(Exception e){
						 System.out.println("Error al obtener el Color de la Banda " +e) ;
					 }
					 productoProyeccion.setAvanceTotalProducto(avanceGeneral);
					 
					 List<ProyeccionProductoPeriodoEntity> listaProyProdPeriodo = null;
					 try{
						 FiltrosSQLBean cadenaFiltros = new FiltrosSQLBean();
						 List<FiltrosBean> listaFiltros = new ArrayList<FiltrosBean>();
						 FiltrosBean filtroCampos = new FiltrosBean();
						 List<String> campos = new ArrayList<String>();
						 campos.add("ppp.periodo_id");
						 campos.add("ppp.producto_id");
						 filtroCampos.setCampos(campos);
						 filtroCampos.setOperador("=");
						 listaFiltros.add(filtroCampos);
						 List<Object> valores = new ArrayList<Object>();
						 valores.add(idPeriodo);
						 valores.add(row.getProducto_id());
						 cadenaFiltros.setListaFiltros(listaFiltros);
						 cadenaFiltros.setListaValores(valores);
						 //4.- Capturamos las proyecciones por producto
						 listaProyProdPeriodo = mantProyeccionProductoPeriodoDao.listaProyeccionProductoPeriodo(cadenaFiltros);
					 }catch(Exception e){
						 System.out.println(mensajeTransaccionMetodo+"Ocurrio un Error al Obtener la lista de proyeccion de productos general- " + e);
						response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
						response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
						return response;
					 }
					 AvancePeriodoProductoBean avancePeriodo = new AvancePeriodoProductoBean(); 
					 BigDecimal montoProyeccionPeriodo = BigDecimal.ZERO;
					 BigDecimal unidadesProyeccionPeriodo = BigDecimal.ZERO;
					 if(listaProyProdPeriodo.size() > 0){
						 for(ProyeccionProductoPeriodoEntity ls : listaProyProdPeriodo){
							 montoProyeccionPeriodo =ls.getCantidad_proyectada().multiply(ls.getPrecio_promedio());
							 unidadesProyeccionPeriodo = ls.getCantidad_proyectada();
							 avancePeriodo.setMontoTotalProyeccionPeriodo(ls.getCantidad_proyectada().multiply(ls.getPrecio_promedio()));
							 avancePeriodo.setUnidadesTotalProyeccionPeriodo(ls.getCantidad_proyectada());
							 try{
								 //5.- capturamos las bandas de la proyeccion por periodo
								 avancePeriodo.setBanda_proyeccion(listaBandas(ls.getCodigo_banda()));
							 }catch(Exception e){
								 avancePeriodo.setBanda_proyeccion(null);
							 }
						 }
					 }
					 List<VentasEntity> ventasPorProductoPeriodo = null;
					 try{
						 FiltrosSQLBean cadenaFiltros = new FiltrosSQLBean();
						 List<FiltrosBean> listaFiltros = new ArrayList<FiltrosBean>();
						 FiltrosBean filtroCampos = new FiltrosBean();
						 List<String> campos = new ArrayList<String>();
						 campos.add("periodo_id");
						 campos.add("producto_id");
						 filtroCampos.setCampos(campos);
						 filtroCampos.setOperador("=");
						 listaFiltros.add(filtroCampos);
						 List<Object> valores = new ArrayList<Object>();
						 valores.add(idPeriodo);
						 valores.add(row.getProducto_id());
						 cadenaFiltros.setListaFiltros(listaFiltros);
						 cadenaFiltros.setListaValores(valores);
						 //6.- Capturamos la venta y unidades total de cada producto y por periodo
						 ventasPorProductoPeriodo = consultaVentasDao.listaVentasDetalle(cadenaFiltros);
					 }catch(Exception e){
						System.out.println(mensajeTransaccionMetodo+"Ocurrio un Error al Obtener la lista de proyeccion de productos general- " + e);
						response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
						response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
						return response;
					 }
					 BigDecimal montoPeriodo= BigDecimal.ZERO;
					 BigDecimal unidadesPeriodo = BigDecimal.ZERO;
					 BigDecimal porcentajePeriodoUnidades=	BigDecimal.ZERO;
					 if(ventasPorProductoPeriodo.size() > 0){
						 for(VentasEntity ventasPeriodo :  ventasPorProductoPeriodo){
							 montoPeriodo = montoPeriodo.add(ventasPeriodo.getTotal());
							 unidadesPeriodo = unidadesPeriodo.add(ventasPeriodo.getCantidad());
						 }
					 }
					 try{
						 porcentajePeriodoUnidades = (montoPeriodo).divide(montoProyeccionPeriodo,4, RoundingMode.CEILING);
					 }catch(Exception e){
						 System.out.println();
						System.out.println("Error al Promediar porcentaje de productos por periodo en unidades " + e);
					 }
					 avancePeriodo.setMontoAvancePeriodo(montoPeriodo);
					 avancePeriodo.setUnidadesAvancePeriodo(unidadesPeriodo);
					 
					 try{
						 avancePeriodo.setPorcentageMontoAvance(porcentajePeriodoUnidades.multiply(new BigDecimal(100)));
					 }catch(Exception e){
						 System.out.println("Error al Obtener el porcentaje por monto de productos por periodo " + e);
						 avancePeriodo.setPorcentageMontoAvance(BigDecimal.ZERO);
					 }
					 try{
						 avancePeriodo.setPorcentageUnidadAvance((unidadesPeriodo.multiply(new BigDecimal(100))).divide(unidadesProyeccionPeriodo,4, RoundingMode.CEILING));
					 }catch(Exception e){
						 System.out.println("Error al Obtener el porcentaje por unidades de productos por periodo " + e);
						 avancePeriodo.setPorcentageUnidadAvance(BigDecimal.ZERO);
					 }
					 
					 try{
						 avancePeriodo.setColorBanda(colorBanda(avancePeriodo.getBanda_proyeccion(),porcentajePeriodoUnidades ));
					 }catch(Exception e){
						 System.out.println("Error al obtener el Color de la Banda " +e) ;
					 }
					 productoProyeccion.setAvancePeriodoProducto(avancePeriodo);
					 listaProyeccionProductos.add(productoProyeccion);
				 }
				 response.setListaAvanceProductos(listaProyeccionProductos);
				 response.setCodigoRespuesta(ConstantesInternasSistema.CODIGO_EXITO);
				 response.setMensajeRespuesta(ConstantesInternasSistema.MENSAJE_EXITO);
				 
			 }else{
				System.out.println(mensajeTransaccionMetodo+"No se encontraron datos de Proyeccion por periodo");
				response.setCodigoRespuesta(ConstModAdministracion.MANT_LISTAR_COD_IDF);
				response.setMensajeRespuesta(ConstModAdministracion.MANT_LISTAR_MSJ_IDF.replace("msj", mensajeTransaccionMetodo));
			 }
		}catch(Exception e){
			System.out.println(mensajeTransaccionMetodo+"Ocurrio un Error en el Proceso - " + e);
			response.setCodigoRespuesta(ConstProyeccion.PROYECCION_LISTAR_COD_IDT);
			response.setMensajeRespuesta(ConstProyeccion.PROYECCION_LISTAR_MSJ_IDT.replace("msj", mensajeTransaccionMetodo));
		}
		return response;
	}

	public List<BigDecimal> listaBandas(String codBanda){
		
		List<BandaProyeccionEntity> listaBandas = null;
		 try{
			 FiltrosSQLBean cadenaFiltros = new FiltrosSQLBean();
			 List<FiltrosBean> listaFiltros = new ArrayList<FiltrosBean>();
			 FiltrosBean filtroCampos = new FiltrosBean();
			 List<String> campos = new ArrayList<String>();
			 campos.add("codigo");
			 filtroCampos.setCampos(campos);
			 filtroCampos.setOperador("=");
			 listaFiltros.add(filtroCampos);
			 List<Object> valores = new ArrayList<Object>();
			 valores.add(codBanda);
			 cadenaFiltros.setListaFiltros(listaFiltros);
			 cadenaFiltros.setListaValores(valores);
			 listaBandas = mantBandaProyeccionDao.listaBandasProyeccion(cadenaFiltros);
		}catch(Exception e){
			System.out.println("Error al Obtener las bandas: " + e);
		}
		 List<BigDecimal> bandas = new ArrayList<BigDecimal>();
		 if(listaBandas.size() > 0 && listaBandas!= null){
			 BigDecimal suma = BigDecimal.ZERO;
			 for(BandaProyeccionEntity ls : listaBandas){
				 suma = suma.add(ls.getPorcentaje());
				 bandas.add(suma);
			 }
		 }
		 
		return bandas;
	}
	
	public String colorBanda(List<BigDecimal> listaBanda, BigDecimal porcentaje){
		
		int i=0;
		for(BigDecimal ls :listaBanda ){
			++i;
			if(porcentaje.compareTo(ls) == -1){
				break;
			}
		}
		String color ="";
		switch(i){
		case 1:
			color = "rojo";
			break;
		case 2:
			color = "amarillo";
			break;
		case 3:
			color = "verde";
			break;
			
		}
		return color;
	};
	
}
